package hu.diploma.android.serviceimpl;

import hu.diploma.android.util.TypeEnumMapper;
import hu.diploma.common.enums.DataType;
import hu.diploma.common.service.AddressService;
import hu.diploma.common.service.PersonService;
import hu.diploma.common.service.PersonalDataService;
import hu.diploma.common.service.StructuredNameService;
import hu.diploma.common.vos.AddressVo;
import hu.diploma.common.vos.GroupVo;
import hu.diploma.common.vos.PersonVo;
import hu.diploma.common.vos.PersonalDataVo;
import hu.diploma.common.vos.StructuredNameVo;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.CommonDataKinds.Website;
import android.util.Log;

public class PersonServiceImpl implements PersonService {

	private final ContentResolver contentResolver;
	private final PersonalDataService peopleDataService;
	private final StructuredNameService structuredNameService;
	private final AddressService addressService;

	public PersonServiceImpl(ContentResolver contentResolver) {
		super();
		this.contentResolver = contentResolver;
		this.peopleDataService = new PersonalDataServiceImpl(contentResolver);
		this.structuredNameService = new StructuredNameServiceImpl(contentResolver);
		this.addressService = new AddressServiceImpl(contentResolver);
	}

	@Override
	public PersonVo save(PersonVo people) throws Exception {

		ContentValues values = new ContentValues();
		values.put(RawContacts.ACCOUNT_TYPE, people.getAccountType() != null ? people.getAccountType() : "vnd.sec.contact.phone");
		values.put(RawContacts.ACCOUNT_NAME, people.getAccountName() != null ? people.getAccountName() : "vnd.sec.contact.phone");
		Uri rawContactUri = this.contentResolver.insert(RawContacts.CONTENT_URI, values);
		long id = ContentUris.parseId(rawContactUri);
		Log.d("DEBUG", "  " + id);
		people.setPhoneId(id);

		if (people.getPersonalDatas() != null) {
			for (PersonalDataVo peopleDataVo : people.getPersonalDatas()) {
				peopleDataVo.setPerson(people);
				peopleDataVo = this.peopleDataService.save(peopleDataVo);
			}
		}
		if (people.getStructuredName() != null) {
			people.getStructuredName().setPerson(people);
			people.setStructuredName(this.structuredNameService.save(people.getStructuredName()));

		}
		if (people.getAddresses() != null) {
			for (AddressVo addressVo : people.getAddresses()) {
				addressVo.setPerson(people);
				addressVo = this.addressService.save(addressVo);
			}
		}
		return people;
	}

	@Override
	public PersonVo merge(PersonVo people) throws Exception {
		if (people.getPhoneId() == null) {
			ContentValues values = new ContentValues();
			values.put(RawContacts.ACCOUNT_TYPE, people.getAccountType() != null ? people.getAccountType() : "vnd.sec.contact.phone");
			values.put(RawContacts.ACCOUNT_NAME, people.getAccountName() != null ? people.getAccountName() : "vnd.sec.contact.phone");
			Uri rawContactUri = this.contentResolver.insert(RawContacts.CONTENT_URI, values);
			long id = ContentUris.parseId(rawContactUri);
			people.setPhoneId(id);
		}

		if (people.getPersonalDatas() != null) {
			for (PersonalDataVo peopleDataVo : people.getPersonalDatas()) {
				peopleDataVo.setPerson(people);
				peopleDataVo = this.peopleDataService.save(peopleDataVo);
			}
		}
		if (people.getStructuredName() != null) {
			people.getStructuredName().setPerson(people);
			people.setStructuredName(this.structuredNameService.save(people.getStructuredName()));

		}
		if (people.getAddresses() != null) {
			for (AddressVo addressVo : people.getAddresses()) {
				addressVo.setPerson(people);
				addressVo = this.addressService.save(addressVo);
			}
		}
		return people;

	}

	@Override
	public PersonVo findById(Serializable searchId) {
		return null;

	}

	@Override
	public List<PersonVo> loadAll() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void delete(PersonVo vo) {
		// TODO Auto-generated method stub

	}

	@Override
	public List<PersonVo> findByGroup(GroupVo groupVo) throws Exception {
		Log.d(this.getClass().getCanonicalName(), "Start: findByGroup ");
		List<PersonVo> peopleVos = new ArrayList<PersonVo>();
		String where = Data.MIMETYPE + "=? and " + GroupMembership.GROUP_ROW_ID + "=? ";
		String[] args = { GroupMembership.CONTENT_ITEM_TYPE, groupVo.getPhoneId().toString() };
		Cursor cursor = this.contentResolver.query(Data.CONTENT_URI, null, where, args, null);
		try {

			while (cursor.moveToNext()) {
				long id = cursor.getLong(cursor.getColumnIndex(GroupMembership.CONTACT_ID));
				Log.d(this.getClass().getCanonicalName(), "contentResolver:" + this.contentResolver);
				PersonService peopleService = new PersonServiceImpl(this.contentResolver);
				peopleVos.add(peopleService.findByPhoneId(id));
			}
			Log.d("DEBUG", "End: findByGroup ");
		} catch (Exception e) {
			Log.e("DEBUG", "End: findByGroup ", e);
		}
		return peopleVos;

	}

	@Override
	public PersonVo findByPhoneId(Serializable searchId) throws Exception {
		Log.d(this.getClass().getCanonicalName(), "Start: findById  " + searchId);
		PersonVo peopleVo = new PersonVo();
		peopleVo.setPhoneId((Long) searchId);
		try {

			String where = ContactsContract.Data.CONTACT_ID + " = ?";
			String[] whereParameters = new String[] { peopleVo.getPhoneId().toString() };
			Cursor cursor = this.contentResolver.query(Data.CONTENT_URI, null, where, whereParameters, null);
			List<AddressVo> addressVos = new ArrayList<AddressVo>();
			List<PersonalDataVo> peopleDataVos = new ArrayList<PersonalDataVo>();

			try {

				while (cursor.moveToNext()) {
					if (cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE)).equals(StructuredPostal.CONTENT_ITEM_TYPE)) {
						Integer id = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
						String poBox = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POBOX));
						String street = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.STREET));
						String city = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY));
						String state = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.REGION));
						String postalCode = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE));
						String country = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY));
						String type = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.TYPE));
						Long version = cursor.getLong(cursor.getColumnIndex(ContactsContract.Data.DATA_VERSION));

						AddressVo addressVo = new AddressVo();
						addressVo.setPhoneId(id.longValue());
						addressVo.setPobox(poBox);
						addressVo.setStreet(street);
						addressVo.setCity(city);
						addressVo.setState(state);
						addressVo.setPostalCode(postalCode);
						addressVo.setCountry(country);
						addressVo.setType(TypeEnumMapper.getAddressTypeMap().get(type));
						addressVo.setVersion(version);
						addressVos.add(addressVo);

					} else if (cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE)).equals(StructuredName.CONTENT_ITEM_TYPE)) {
						StructuredNameVo structuredName = new StructuredNameVo();
						Integer id = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
						String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME));
						String familName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
						String middleName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME));
						String givenName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
						String preixName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.PREFIX));
						Long version = cursor.getLong(cursor.getColumnIndex(ContactsContract.Data.DATA_VERSION));

						structuredName.setPhoneId(id.longValue());
						structuredName.setDisplayName(displayName);
						structuredName.setFamilName(familName);
						structuredName.setMiddleName(middleName);
						structuredName.setGivenName(givenName);
						structuredName.setPreixName(preixName);
						structuredName.setVersion(version);
						peopleVo.setStructuredName(structuredName);

					} else if (cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE)).equals(Im.CONTENT_ITEM_TYPE)) {
						String value = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA));
						Integer type = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Im.PROTOCOL));
						Integer id = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
						Long version = cursor.getLong(cursor.getColumnIndex(ContactsContract.Data.DATA_VERSION));

						PersonalDataVo peopleDataVo = new PersonalDataVo();
						peopleDataVo.setPhoneId(id.longValue());
						peopleDataVo.setType(DataType.IM);
						peopleDataVo.setSubtype(TypeEnumMapper.getImTypeMap().get(type));
						peopleDataVo.setValue(value);
						peopleDataVo.setVersion(version);
						peopleDataVos.add(peopleDataVo);

					} else if (cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE)).equals(Email.CONTENT_ITEM_TYPE)) {
						PersonalDataVo peopleDataVo = new PersonalDataVo();
						Integer phoneId = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
						Integer type = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));
						String value = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
						Long version = cursor.getLong(cursor.getColumnIndex(ContactsContract.Data.DATA_VERSION));

						peopleDataVo.setPhoneId(phoneId.longValue());
						peopleDataVo.setType(DataType.EMAIL);
						peopleDataVo.setSubtype(TypeEnumMapper.getEmailTypeMap().get(type));
						peopleDataVo.setValue(value);
						peopleDataVo.setVersion(version);
						peopleDataVos.add(peopleDataVo);

					} else if (cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE)).equals(Event.CONTENT_ITEM_TYPE)) {
						String value = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Event.DATA));
						Integer type = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Event.TYPE));
						Integer id = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
						Long version = cursor.getLong(cursor.getColumnIndex(ContactsContract.Data.DATA_VERSION));
						PersonalDataVo peopleDataVo = new PersonalDataVo();

						peopleDataVo.setPhoneId(id.longValue());
						peopleDataVo.setType(DataType.EVENT);
						peopleDataVo.setSubtype(TypeEnumMapper.getEventTypeMap().get(type));
						peopleDataVo.setValue(value);
						peopleDataVos.add(peopleDataVo);

						peopleDataVo.setVersion(version);

					} else if (cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE)).equals(Phone.CONTENT_ITEM_TYPE)) {
						PersonalDataVo peopleDataVo = new PersonalDataVo();
						Integer phoneId = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
						Integer type = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
						String value = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DATA));
						Long version = cursor.getLong(cursor.getColumnIndex(ContactsContract.Data.DATA_VERSION));

						peopleDataVo.setPhoneId(phoneId.longValue());
						peopleDataVo.setType(DataType.PHONE);
						peopleDataVo.setSubtype(TypeEnumMapper.getPhoneTypeMap().get(type));
						peopleDataVo.setValue(value);
						peopleDataVo.setVersion(version);
						peopleDataVos.add(peopleDataVo);

					} else if (cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE)).equals(Website.CONTENT_ITEM_TYPE)) {
						String value = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Website.URL));
						Integer type = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Website.TYPE));
						Integer id = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
						PersonalDataVo peopleDataVo = new PersonalDataVo();
						Long version = cursor.getLong(cursor.getColumnIndex(ContactsContract.Data.DATA_VERSION));

						peopleDataVo.setPhoneId(id.longValue());
						peopleDataVo.setType(DataType.NOTE);
						peopleDataVo.setSubtype(TypeEnumMapper.getWebsiteTypeMap().get(type));
						peopleDataVo.setValue(value);
						peopleDataVo.setVersion(version);
						peopleDataVos.add(peopleDataVo);
					} else if (cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE)).equals(Website.CONTENT_ITEM_TYPE)) {
						PersonalDataVo peopleDataVo = new PersonalDataVo();
						String nickname = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Nickname.NAME));
						Integer id = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
						Long version = cursor.getLong(cursor.getColumnIndex(ContactsContract.Data.DATA_VERSION));

						peopleDataVo.setPhoneId(id.longValue());
						peopleDataVo.setType(DataType.NICKNAME);
						peopleDataVo.setValue(nickname);
						peopleDataVo.setVersion(version);
						peopleDataVos.add(peopleDataVo);
					} else if (cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE)).equals(Website.CONTENT_ITEM_TYPE)) {
						String note = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Note.NOTE));
						Integer id = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
						Long version = cursor.getLong(cursor.getColumnIndex(ContactsContract.Data.DATA_VERSION));

						PersonalDataVo peopleDataVo = new PersonalDataVo();
						peopleDataVo.setPhoneId(id.longValue());
						peopleDataVo.setType(DataType.NOTE);
						peopleDataVo.setValue(note);
						peopleDataVo.setVersion(version);
						peopleDataVos.add(peopleDataVo);

					} else if (cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE)).equals(Website.CONTENT_ITEM_TYPE)) {
						PersonalDataVo peopleDataVo = new PersonalDataVo();
						Integer id = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
						Integer type = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TYPE));
						String orgName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.DATA));
						String title = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TITLE));
						Long version = cursor.getLong(cursor.getColumnIndex(ContactsContract.Data.DATA_VERSION));

						peopleDataVo.setValue(orgName);
						peopleDataVo.setType(DataType.ORGANIZATION);
						peopleDataVo.setSubtype(TypeEnumMapper.getOrganizationTypeMap().get(type));
						peopleDataVo.setSubValue(title);
						peopleDataVo.setPhoneId(id.longValue());
						peopleDataVo.setVersion(version);
						peopleDataVos.add(peopleDataVo);

					}

				}
			} catch (Exception e) {
				Log.d("DEBUG", "load personByID ", e);

			} finally {

				cursor.close();
			}

			peopleVo.setPersonalDatas(peopleDataVos);
			peopleVo.setAddresses(addressVos);

		} catch (Exception e) {
			Log.d(this.getClass().getCanonicalName(), "error: searchId ");
		}
		Log.d(this.getClass().getCanonicalName(), "End: findById ");
		return peopleVo;
	}
}
